#include <LOGR_functions.h>
#include <LOGR_users.h>
#include <LOGR_gen_pages.h>
#include <LOGR_gen_info.h>
#include <LOGR_sites.h>
#include <LOGR_browsers.h>
#include <LOGR_create_webgraph.h>
#include <LOGR_independent_links.h>
#include <LOGR_independent_pages.h>
#include <LOGR_gen_links.h>

#include <llist.h>

#include "perror_exit.h"
#include "llist_convert.h"
#include "server_protocol.h"
#include "w3ld.h"
#include "watch.h"

/*
 *	List Functions all return LNode Lists of structs of 
 * data type and data
 */

W3L_FUNC_RETURN W3LD_string_cvt(void *data) {
	if(!data)
		return W3L_FUNC_ERR(W3L_ERR_NULL);
	return construct_return(strdup((char *)data),DATA_TYPE_STRING,strlen((char *)data),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_browser_ua_cvt(void *data) {
	WebBrowserNodePtr wbn = NULL;
	char *info = NULL;

	if((wbn=(WebBrowserNodePtr)data) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if((info=(char *)LOGR_get_user_agent(wbn))==NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	return construct_return(strdup(info),DATA_TYPE_STRING,strlen(info),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_browser_platform_cvt(void *data) {
	WebBrowserNodePtr wbn = NULL;
	char *info = NULL;

	if((wbn=(WebBrowserNodePtr)data) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	switch(LOGR_get_ua_platform(wbn)) {
	case POS2:
		info = strdup("IBM OS/2");
		break;
	case PUNIX:
		info = strdup("*nix");
		break;
	case PMACINTOSH:
		info = strdup("Macintosh");
		break;
	case PWINDOWS95:
		info = strdup("Microsoft Windows 95");
		break;
	case PWINDOWS98:
		info = strdup("Microsoft Windows 98");
		break;
	case PWINDOWSNT:
		info = strdup("Microsoft Windows NT");
		break;
	case PWINDOWS31:
		info = strdup("Microsoft Windows 3.1");
		break;
	default:
		info = strdup("Unknown");
	}

	return construct_return(strdup(info),DATA_TYPE_STRING,strlen(info),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_browser_cvt(void *data) {
	WebBrowserNodePtr wbn = NULL;
	char *info = NULL;

	if((wbn=(WebBrowserNodePtr)data) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	switch(LOGR_get_ua_browser(wbn)) {
	case BOPERA:
		info = strdup("Opera");
		break;
	case BLYNX:
		info = strdup("Lynx");
		break;
	case BMSIE:
		info = strdup("Microsoft Internet Explorer");
		break;
	case OTHER_NETSCAPE_COMP:
		info = strdup("Netscape Compatible");
		break;
	case BNETSCAPE:
		info = strdup("Mozilla/Netscape");
		break;
	default:
		info = strdup("Unknown");
	}

	return construct_return(strdup(info),DATA_TYPE_STRING,strlen(info),FREE_DATA);

}

W3L_FUNC_RETURN W3LD_gen_info_ptr_cvt(void *data) {
	WebGenInfoPtr wgi = NULL;
	char *domain = NULL;
	if((wgi=(WebGenInfoPtr)data) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if((domain=(char *)LOGR_get_gen_info_context(wgi)) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);
	
	return construct_return(strdup(domain), DATA_TYPE_STRING,strlen(domain),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_web_site_node_ptr_cvt(void *data) {
	WebSiteNodePtr wsn = NULL;
	char *site = NULL;

	if((wsn=(WebSiteNodePtr)data) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if((site=(char *)LOGR_get_site_dns(wsn)) == NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	return construct_return(strdup(site), DATA_TYPE_STRING, strlen(site),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_web_user_ptr_cvt(void *data) {
	WebUserPtr wup = NULL;
	char *uname = NULL;

	if(!(wup=(WebUserPtr)data))
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if(!(uname=LOGR_get_user_name(wup)))
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	return construct_return(strdup(uname),DATA_TYPE_STRING,strlen(uname),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_gen_page_cvt(void *data) {
	WebGenPagePtr wgpp = NULL;
	PNODE node = NULL;
	char *label = NULL;
	
	if((wgpp = (WebGenPagePtr)data)==NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if((node = (PNODE)wgpp->nodeptr)==NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);
	
	if((label = strdup(node->label))==NULL)
		return W3L_FUNC_ERR(W3L_ERR_NULL);
	
	return construct_return(label,DATA_TYPE_STRING,strlen(label),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_path_cvt(void *data) {
	WebGenLinkPtr wglp;
	char *line = strdup("");
	char ntmp[32];
	int i;
	const char *tmp;
	
	if(!(wglp  = (WebGenLinkPtr)data))
		return W3L_FUNC_ERR(W3L_ERR_NULL);

	if((tmp = LOGR_get_gen_url_source(wglp)))
		line = concatenate(line,tmp);
	else
		line = concatenate(line," ");
	line = concatenate(line,"\t");

	if((tmp = LOGR_get_gen_mime_source(wglp)))
		line = concatenate(line,tmp);
	else
		line = concatenate(line," ");
	line = concatenate(line,"\t");

	if((i = LOGR_get_gen_http_code_source(wglp)))
		snprintf(ntmp,32,"%d",i);
	else
		strcpy(ntmp," ");
	line = concatenate(line,ntmp);
	line = concatenate(line,"\t");

	if((tmp = LOGR_get_gen_url_target(wglp)))
		line = concatenate(line,tmp);
	else
		line = concatenate(line," ");
	line = concatenate(line,"\t");

	return construct_return(line,DATA_TYPE_STRING,strlen(line),FREE_DATA);
}

W3L_FUNC_RETURN watch_convert(void *data)
{
	char *line;
	w3lWatch *watch = (w3lWatch *)data;
	if(watch->arg_is_string)
		line = cat("\t[%d] %s (%s)",watch->id,watch->description, (char *)(watch->arg));
	else
		line = cat("\t[%d] %s",watch->id,watch->description);
	
	return construct_return(line,DATA_TYPE_STRING,strlen(line),FREE_DATA);
}

W3L_FUNC_RETURN W3LD_cmd_ret_cvt(void *data) {
	w3l_cmd_entry *r = (w3l_cmd_entry *)data;
	char *line = NULL;
	int i;
	assert(r!=NULL);
	line = concatenate(line,r->fname);
	line = concatenate(line,"(");
	for(i=0;i<r->arity;i++) {
		line = concatenate(line,r->arguments[i]);
		if(i+1 != r->arity)
			line = concatenate(line,", ");
	}
	line = concatenate(line,")\n\t");
	line = concatenate(line,r->fdesc);
	return construct_return(line,DATA_TYPE_STRING,strlen(line),FREE_DATA);
}

LNode_type *W3LD_build_list(LNode_type *list, cmd_ret *((*convert)())) {
/*
 * This takes a Linked List, and a function for converting the
 * each list element into a 'list_item' structure (as defined
 * in server_protocol.h for insertion into a new list which may
 * be sent to a client
 *
 * A NULL from (convert) is simply not included in the list.
 */
	LNode_type *ret = NULL,
		*ptr = NULL;
	cmd_ret *c;

	ret = init_linked_list();
	assert(ret != NULL);
	assert(list != NULL);
	assert(convert != NULL);

	for(ptr = list->back; ptr != list && ptr != NULL; ptr = ptr->back) {
		assert(ptr->info != NULL);
		if((c = (*convert)((void *)ptr->info)))
			Insert_linked_list(ret, create_new_node_llist((char *)c));
	}
	return ret;
}

LNode_type *W3LD_build_HTList(HTList *list, cmd_ret *((*convert)())) {
	LNode_type *ret = NULL;
	HTList *cur = NULL;
	void *ptr = NULL;
	cmd_ret *c;

	ret = init_linked_list();
	cur = list;
	assert(ret != NULL);
	assert(list != NULL);
	assert(convert != NULL);

	while ((ptr = HTList_nextObject(cur))) {
		assert(ptr!=NULL);
		if((c = (*convert)((void *)ptr)))
			Insert_linked_list(ret, create_new_node_llist((char *)c));
	}
	return ret;
}
